/*global pi, ArrayBuffer */

pi.mod.define('pi.vfs', function (pi) {
	"use strict";
	var getFullPath, module = {},

		/* vfs的当前路径,用于将所有传递给底层的路径全部转为绝对路径 */
		cwd = "/$root/",
		vcalls = [
			["pi_vfs_mount", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING, pi.vcall.TYPE_STRING, pi.vcall.TYPE_INT, pi.vcall.TYPE_STRING]],
			["pi_vfs_unmount", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING]],
			["pi_vfs_is_path", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING]],
			["pi_vfs_collate", pi.vcall.TYPE_VOID, [pi.vcall.TYPE_LONG]],
			["pi_vfs_get_info", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING, pi.vcall.TYPE_POINTER]],
			["pi_vfs_get_size", pi.vcall.TYPE_LONG, [pi.vcall.TYPE_STRING]],

			["pi_vfs_set_time", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING, pi.vcall.TYPE_LONG, pi.vcall.TYPE_LONG]],

			["pi_vfs_rename", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING, pi.vcall.TYPE_STRING, pi.vcall.TYPE_INT]],

			["pi_vfs_copy", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING, pi.vcall.TYPE_STRING, pi.vcall.TYPE_INT]],

			["pi_vfs_dir_create", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING]],

			["pi_vfs_dir_delete", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING]],

			["pi_vfs_create_path", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING]],

			["pi_vfs_delete_path", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING]],

			["pi_vfs_dir_open", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING]],

			["pi_vfs_dir_read", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_POINTER]],

			["pi_vfs_dir_close", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT]],

			["pi_vfs_file_delete", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING]],

			["pi_vfs_get_crc32", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING, pi.vcall.TYPE_POINTER]],

			["pi_vfs_file_open", pi.vcall.TYPE_INT, [pi.vcall.TYPE_STRING, pi.vcall.TYPE_INT]],

			["pi_vfs_file_close", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT]],

			["pi_vfs_file_size", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_POINTER]],

			["pi_vfs_file_crc", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_POINTER]],

			["pi_vfs_file_read", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_LONG, pi.vcall.TYPE_INT, pi.vcall.TYPE_POINTER, pi.vcall.TYPE_INT]],

			["pi_vfs_file_write", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_LONG, pi.vcall.TYPE_INT, pi.vcall.TYPE_POINTER, pi.vcall.TYPE_INT]],

			["pi_vfs_file_truncate", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_LONG]],

			["pi_error_get", pi.vcall.TYPE_INT, []]

		];

	// 磁盘文件系统，这时param为磁盘某个目录的绝对路径
	module.MOD_NAME_FILE = "file";

	// 内存文件系统，这时param为null
	module.MOD_NAME_MEM = "mem";

	// sqlite文件系统，这时param为db文件的绝对路径
	module.MOD_NAME_SQLITE = "vfs_sqlite";

	/* 文件 */
	module.FILE_TYPE_REGULAR = 1; /* 目录 */
	module.FILE_TYPE_DIRECTORY = 2; /* 连接 */
	module.FILE_TYPE_SYMLINK = 3; /* 设备 */
	module.FILE_TYPE_DEVICE = 4; /* 其他 */
	module.FILE_TYPE_OTHER = 11;

	/* 读，如果文件不存在则报错 */
	module.FILE_OPEN_READ = 1; /* 写，如果文件不存在则创建 */
	module.FILE_OPEN_WRITE = 2; /* 写选项，清空文件 */
	module.FILE_OPEN_WRITE_CLEAR = 4; /* 独占 */
	module.FILE_OPEN_EXCLUSIVE = 8;

	// 注册所有 vcall 函数句柄
	pi.vcall.makeVCall("pi_lib.dll", module, vcalls);

	/*
	 * 如果时相对路径,则转为绝对路径,使用cwd
	 */
	getFullPath = function (path) {
		if (path.charAt(0) !== "/" && path.charAt(1) !== ":") {
			path = cwd + path;
		}
		return path;
	};

	/**
	 * 设置当前路径
	 */
	module.setCwd = function (path) {
		cwd = path;
	};

	/**
	 * 获取当前路径
	 */
	module.getCwd = function () {
		return cwd;
	};

	/**
	 * 加载文件系统
	 * vfsPath: string, 加载的vfs路径
	 * modName: string, 加载的模块名，见上面的MOD_NAME_*变量
	 * fileOpenMode: int, 当该模块为vfs_sqlite时，该参数表示是只读还是只写
	 * param: string, 加载的模块参数，具体见MOD_NAME_*变量的注释
	 * 返回：bool，表示是否成功
	 */
	module.mount = function (vfsPath, modName, fileOpenMode, param) {
		return 1 === vcalls.pi_vfs_mount(vfsPath, modName, fileOpenMode, param);
	};

	/**
	 * 卸载文件系统
	 * vfsPath: string, 加载的vfs路径
	 * 返回：bool，表示是否成功
	 */
	module.unmount = function (vfsPath) {
		return 1 === vcalls.pi_vfs_unmount(vfsPath);
	};

	/**
	 * 判断一个路径是否是vfs路径
	 * path: string, 加载的vfs路径
	 * 返回：bool，路径path是否是vfs路径
	 */
	module.isVfsPath = function (path) {
		path = getFullPath(path);
		return 1 === vcalls.pi_vfs_is_path(path);
	};

	/**
	 * 整理所有的vfs模块
	 * time: int，时间点
	 * 返回：无返回值
	 */
	module.collate = function (path) {
		path = getFullPath(path);
		vcalls.pi_vfs_collate(path);
	};

	/**
	 * 取对应文件的信息
	 * path: string, 文件的vfs路径
	 * 返回：失败返回undefined，成功返回对象
	 * {
	 *	type: int, 类型，值见FILE_TYPE_*常量
	 *	createTime: double, 创建文件时间，单位：毫秒
	 *	writeTime: double, 最近修改文件时间，单位：毫秒
	 *	size: double, 字节数
	 * }
	 */
	module.getInfo = function (path) {
		var r, desc, status, tempBuf;
		tempBuf = new ArrayBuffer(32);
		path = getFullPath(path);
		status = vcalls.pi_vfs_get_info(path, tempBuf);
		r = undefined;
		if (status === 1) {
			desc = ["type", pi.vcall.TYPE_UINT, "temp", pi.vcall.TYPE_INT, "createTime", pi.vcall.TYPE_LONG, "writeTime", pi.vcall.TYPE_LONG, "size", pi.vcall.TYPE_LONG];
			r = pi.vcall.createObjectFromBuffer(tempBuf, desc);
			delete r.temp;
		}
		return r;
	};

	/**
	 * 取对应文件的大小
	 * path: string, 文件的vfs路径
	 * 返回：失败返回-1，成功返回对应文件的字节数
	 */
	module.getSize = function (path) {
		path = getFullPath(path);
		return vcalls.pi_vfs_get_size(path);
	};

	/**
	 * 设置时间
	 * path：string，文件的vfs路径
	 * createTime: 创建时间，单位：毫秒；
	 * writeTime: 修改时间，单位：毫秒；
	 * 返回：bool，表示是否成功
	 */
	module.setTime = function (path, createTime, writeTime) {
		path = getFullPath(path);
		return 1 === vcalls.pi_vfs_set_time(path, createTime, writeTime);
	};

	/**
	 * 重命名
	 * oldPath：string，文件的旧vfs路径
	 * newPath：string，文件的新vfs路径
	 * 返回：bool，表示是否成功
	 */
	module.rename = function (oldPath, newPath) {
		return 1 === vcalls.pi_vfs_rename(oldPath, newPath, 1024 * 1024);
	};

	/**
	 * 拷贝文件
	 * oldPath：string，文件的旧vfs路径
	 * newPath：string，文件的新vfs路径
	 * 返回：bool，表示是否成功
	 */
	module.copy = function (oldPath, newPath) {
		return 1 === vcalls.pi_vfs_copy(oldPath, newPath, 1024 * 1024);
	};

	/**
	 * 创建目录：
	 * path：string，目录的vfs路径
	 * 返回：bool，表示是否成功
	 */
	module.createDir = function (path) {
		path = getFullPath(path);
		return 1 === vcalls.pi_vfs_dir_create(path);
	};

	/**
	 * 删除空目录：
	 * path：string，目录的vfs路径
	 * 返回：bool，表示是否成功
	 */
	module.deleteDir = function (path) {
		path = getFullPath(path);
		return 1 === vcalls.pi_vfs_dir_delete(path);
	};

	/**
	 * 逐层创建目录：
	 * path：string，目录的vfs路径，必须以'/'分割目录
	 * 返回：bool，表示是否成功
	 */
	module.createPath = function (path) {
		path = getFullPath(path);
		return 1 === vcalls.pi_vfs_create_path(path);
	};

	/**
	 * 递归删除path下的所有文件，包括path
	 * path：string，目录的vfs路径，必须以'/'分割目录
	 * 返回：bool，表示是否成功
	 */
	module.deletePath = function (path) {
		path = getFullPath(path);
		return 1 === vcalls.pi_vfs_delete_path(path);
	};

	/**
	 * 打开目录：
	 * path: 目录的vfs路径
	 * 返回：int，返回目录迭代器句柄，失败返回0
	 */
	module.openDir = function (path) {
		path = getFullPath(path);
		return vcalls.pi_vfs_dir_open(path);
	};

	/**
	 * 读取目录项：
	 * dirIter: 目录的迭代器句柄
	 * 返回：失败返回0，成功返回对象
	 * {
	 *		type, int, 文件类型，见上面变量FILE_TYPE_*
	 *		createTime，double，创建时间，单位：毫秒
	 *		writeTime：double，最近修改时间，单位：毫秒
	 *		size：double，文件字节数
	 *		name：string，相对于本目录的路径
	 */
	module.readDir = function (dirIter) {
		var r, desc, status,
			tempBuf = new ArrayBuffer(552);
		status = vcalls.pi_vfs_dir_read(dirIter, tempBuf);
		r = undefined;
		if (status === 1) {
			desc = ["type", pi.vcall.TYPE_UINT, "temp", pi.vcall.TYPE_INT, "createTime", pi.vcall.TYPE_LONG, "writeTime", pi.vcall.TYPE_LONG, "size", pi.vcall.TYPE_LONG, "name", pi.vcall.TYPE_STRING];
			r = pi.vcall.createObjectFromBuffer(tempBuf, desc);
			delete r.temp;
		}
		return r;
	};

	/**
	 * 关闭目录：
	 * dirIter: 目录迭代器句柄
	 * 返回：bool，关闭是否成功
	 */
	module.closeDir = function (dirIter) {
		return 1 === vcalls.pi_vfs_dir_close(dirIter);
	};

	/**
	 * 删除文件：
	 * path: 文件对应的vfs路径
	 * 返回：bool，删除是否成功
	 */
	module.deleteFile = function (path) {
		path = getFullPath(path);
		return 1 === vcalls.pi_vfs_file_delete(path);
	};

	/**
	 * 获取文件的crc：
	 * path: 文件对应的vfs路径
	 * 返回：int，crc值，失败返回0
	 */
	module.GetCrc32 = function (path) {
		var crc, status, byteBuf, tempBuf;
		tempBuf = new ArrayBuffer(4);
		path = getFullPath(path);
		status = vcalls.pi_vfs_get_crc32(path, tempBuf);
		crc = 0;
		if (status === 1) {
			byteBuf = pi.jsByteBuffer();
			byteBuf.buf = tempBuf;
			crc = byteBuf.readInt();
		}
		return crc;
	};

	/**
	 * 打开文件
	 * path: string, 文件对应的vfs路径
	 * openMode: int, 打开模式 值为module.FILE_OPEN_*之一
	 * 返回：int，文件句柄，失败返回0
	 */
	module.openFile = function (path, openMode) {
		path = getFullPath(path);
		return vcalls.pi_vfs_file_open(path, openMode);
	};

	/**
	 * 关闭文件
	 * file: 文件句柄
	 * 返回：bool，关闭是否成功
	 */
	module.closeFile = function (file) {
		return 1 === vcalls.pi_vfs_file_close(file);
	};

	/**
	 * 取文件大小
	 * file: 文件句柄
	 * 返回：int，文件字节数，返回-1表示操作失败
	 */
	module.getFileSize = function (file) {
		var size, status, tempBuf;
		// int64*
		tempBuf = new ArrayBuffer(8);
		status = vcalls.pi_vfs_file_size(file, tempBuf);
		size = -1;
		if (status === 1) {
			size = pi.vcall.readBuffer(tempBuf, pi.vcall.TYPE_INT);
		}
		return size;
	};

	/**
	 * 取文件CRC
	 * file: 文件句柄
	 * 返回：int，CRC，返回0表示操作失败
	 */
	module.getFileCrc = function (file) {
		var crc, status, tempBuf, byteBuf;
		tempBuf = new ArrayBuffer(4);
		status = vcalls.pi_vfs_file_crc(file, tempBuf);
		crc = 0;
		if (status === 1) {
			byteBuf = pi.jsByteBuffer();
			byteBuf.buf = tempBuf;
			crc = byteBuf.readInt();
		}
		return crc;
	};

	/**
	 * 读文件
	 * file: int，文件句柄
	 * offset: double，偏移量
	 * isFromEnd: bool，offset是否从末尾算起
	 * size: int，读多少字节
	 * 返回：ArrayBuffer, 失败返回undefined
	 */
	module.readFile = function (file, offset, isFromEnd, size) {
		var status,
			r = new ArrayBuffer(size);
		status = vcalls.pi_vfs_file_read(file, offset, isFromEnd ? 1 : 0, r, size);
		if (status < 0) {
			r = undefined;
		}
		return r;
	};

	/**
	 * 读文件到C内存
	 * file: int，文件句柄
	 * offset: double，偏移量
	 * isFromEnd: bool，offset是否从末尾算起
	 * size: int，读多少字节
	 * 返回：int, 内存句柄，失败返回0
	 */
	module.readFileMem = function (file, offset, isFromEnd, size) {
		var r = pi.mem.malloc(size),
			status = vcalls.pi_vfs_file_read(file, offset, isFromEnd ? 1 : 0, r, size);
		if (status < 0) {
			pi.mem.free(r);
			r = 0;
		}
		return r;
	};

	/**
	 * 写文件
	 * file: int，文件句柄
	 * offset: double, 偏移量
	 * isFromEnd：bool，是否从末尾开始
	 * buf：ArrayBuffer，写文件的内容
	 * 返回：bool，是否成功
	 */
	module.writeFile = function (file, offset, isFromEnd, buf) {
		return 1 === vcalls.pi_vfs_file_write(file, offset, isFromEnd ? 1 : 0, buf, buf.byteLength);
	};

	/**
	 * 设置文件大小
	 * file: int，文件句柄
	 * size：double，文件字节数
	 * 返回：bool，是否成功
	 */
	module.setFileSize = function (file, size) {
		return 1 === vcalls.pi_vfs_file_truncate(file, size);
	};

	/**
	 * 设置最近错误信息
	 * 返回：对象
	 * {
	 *    type: int, 类型
	 *    code: int, 错误码
	 *    msg: string, 信息
	 *    file：string，文件
	 *    line：int，行号
	 * }
	 */
	module.getError = function () {
		var PEO_TYPE = 0,
			// PiError offsets, see pi_error.h
			PEO_CODE = 4,
			PEO_MSG = 8,
			PEO_FILE = 560 + 8,
			PEO_LINE = 260 + PEO_FILE,
			// 828
			PEO_SIZE = PEO_LINE + 4, // 832
			r = vcalls.pi_error_get();
		return {
			type: pi.vcall.readBuffer(r, pi.vcall.TYPE_INT, PEO_TYPE),
			code: pi.vcall.readBuffer(r, pi.vcall.TYPE_INT, PEO_CODE),
			msg: pi.vcall.readBuffer(r, pi.vcall.TYPE_STRING, PEO_MSG),
			file: pi.vcall.readBuffer(r, pi.vcall.TYPE_ANSI_STRING, PEO_FILE),
			line: pi.vcall.readBuffer(r, pi.vcall.TYPE_INT, PEO_LINE)
		};
	};
	return module;
});